image: use gtk_render_icon()
authorCosimo Cecchi <cosimoc@gnome.org>
Sat, 21 May 2011 03:51:37 +0000 (23:51 -0400)
committerBenjamin Otte <otte@redhat.com>
Thu, 9 Jun 2011 21:17:09 +0000 (23:17 +0200)
gtk/gtkimage.c

index c6ba2947e07a9a987aea4c73e08dd33c076c36e3..1c9c0a3d0726d83cc40e47cb80683b17a59ef373 100644 (file)
@@ -153,7 +153,6 @@ struct _GtkImagePrivate
   gint                  required_height;
   guint                 need_calc_size : 1;
   guint                 use_fallback   : 1;
-  guint                 was_symbolic   : 1;
 };
 
 
@@ -1426,15 +1425,133 @@ icon_theme_changed (GtkImage *image)
 }
 
 static void
-ensure_pixbuf_for_icon_name (GtkImage      *image,
-                             GtkStateFlags  state)
+ensure_icon_size (GtkImage *image,
+                 GtkIconLookupFlags *flags,
+                 gint *width_out,
+                 gint *height_out)
+{
+  GtkImagePrivate *priv = image->priv;
+  gint width, height;
+  GtkSettings *settings;
+  GdkScreen *screen;
+  GtkIconTheme *icon_theme;
+  gint *s, *sizes, dist;
+
+  screen = gtk_widget_get_screen (GTK_WIDGET (image));
+  settings = gtk_settings_get_for_screen (screen);
+  icon_theme = gtk_icon_theme_get_for_screen (screen);
+
+  if (priv->pixel_size != -1)
+    {
+      width = height = priv->pixel_size;
+      *flags |= GTK_ICON_LOOKUP_FORCE_SIZE;
+    }
+  else if (!gtk_icon_size_lookup_for_settings (settings,
+                                              priv->icon_size,
+                                              &width, &height))
+    {
+      if (priv->icon_size == -1)
+       {
+         /* Find an available size close to 48 */
+         sizes = gtk_icon_theme_get_icon_sizes (icon_theme, priv->data.name.icon_name);
+         dist = 100;
+         width = height = 48;
+         for (s = sizes; *s; s++)
+           {
+             if (*s == -1)
+               {
+                 width = height = 48;
+                 break;
+               }
+             if (*s < 48)
+               {
+                 if (48 - *s < dist)
+                   {
+                     width = height = *s;
+                     dist = 48 - *s;
+                   }
+               }
+             else
+               {
+                 if (*s - 48 < dist)
+                   {
+                     width = height = *s;
+                     dist = *s - 48;
+                   }
+               }
+           }
+         g_free (sizes);
+       }
+      else
+       {
+         g_warning ("Invalid icon size %d\n", priv->icon_size);
+         width = height = 24;
+       }
+    }
+
+  *width_out = width;
+  *height_out = height;
+}
+
+static GdkPixbuf *
+ensure_stated_icon_from_info (GtkImage *image,
+                             GtkIconInfo *info)
+{
+  GtkImagePrivate *priv = image->priv;
+  GtkStyleContext *context;
+  GdkPixbuf *destination;
+  gboolean symbolic;
+
+  context = gtk_widget_get_style_context (GTK_WIDGET (image));
+  symbolic = FALSE;
+
+  if (info)
+    destination =
+      gtk_icon_info_load_symbolic_for_context (info,
+                                              context,
+                                              &symbolic,
+                                              NULL);
+
+  if (destination == NULL)
+    {
+      destination =
+       gtk_widget_render_icon_pixbuf (GTK_WIDGET (image),
+                                      GTK_STOCK_MISSING_IMAGE,
+                                      priv->icon_size);
+    }
+  else if (!symbolic)
+    {
+      GtkIconSource *source;
+      GdkPixbuf *rendered;
+
+      source = gtk_icon_source_new ();
+      gtk_icon_source_set_pixbuf (source, destination);
+      /* The size here is arbitrary; since size isn't
+       * wildcarded in the source, it isn't supposed to be
+       * scaled by the engine function
+       */
+      gtk_icon_source_set_size (source,
+                               GTK_ICON_SIZE_SMALL_TOOLBAR);
+      gtk_icon_source_set_size_wildcarded (source, FALSE);
+
+      rendered = gtk_render_icon_pixbuf (context, source, (GtkIconSize) -1);
+      gtk_icon_source_free (source);
+
+      g_object_unref (destination);
+      destination = rendered;
+    }
+
+  return destination;
+}
+
+static void
+ensure_pixbuf_for_icon_name (GtkImage        *image,
+                             GtkStateFlags    state)
 {
   GtkImagePrivate *priv = image->priv;
   GdkScreen *screen;
   GtkIconTheme *icon_theme;
-  GtkSettings *settings;
   gint width, height;
-  gint *sizes, *s, dist;
   GtkIconInfo *info;
   GtkIconLookupFlags flags;
 
@@ -1442,104 +1559,42 @@ ensure_pixbuf_for_icon_name (GtkImage      *image,
 
   screen = gtk_widget_get_screen (GTK_WIDGET (image));
   icon_theme = gtk_icon_theme_get_for_screen (screen);
-  settings = gtk_settings_get_for_screen (screen);
+
   flags = GTK_ICON_LOOKUP_USE_BUILTIN;
+
   if (priv->use_fallback)
     flags |= GTK_ICON_LOOKUP_GENERIC_FALLBACK;
-  if (priv->data.name.pixbuf == NULL ||
-      (priv->was_symbolic && priv->last_rendered_state != state))
+
+  if ((priv->data.name.pixbuf == NULL) ||
+      (priv->last_rendered_state != state))
     {
       priv->last_rendered_state = state;
+
       if (priv->data.name.pixbuf)
         {
           g_object_unref (priv->data.name.pixbuf);
           priv->data.name.pixbuf = NULL;
        }
-      if (priv->pixel_size != -1)
-       {
-         width = height = priv->pixel_size;
-          flags |= GTK_ICON_LOOKUP_FORCE_SIZE;
-       }
-      else if (!gtk_icon_size_lookup_for_settings (settings,
-                                                  priv->icon_size,
-                                                  &width, &height))
-       {
-         if (priv->icon_size == -1)
-           {
-             /* Find an available size close to 48 */
-             sizes = gtk_icon_theme_get_icon_sizes (icon_theme, priv->data.name.icon_name);
-             dist = 100;
-             width = height = 48;
-             for (s = sizes; *s; s++)
-               {
-                 if (*s == -1)
-                   {
-                     width = height = 48;
-                     break;
-                   }
-                 if (*s < 48)
-                   {
-                     if (48 - *s < dist)
-                       {
-                         width = height = *s;
-                         dist = 48 - *s;
-                       }
-                   }
-                 else
-                   {
-                     if (*s - 48 < dist)
-                       {
-                         width = height = *s;
-                         dist = *s - 48;
-                       }
-                   }
-               }
-             g_free (sizes);
-           }
-         else
-           {
-             g_warning ("Invalid icon size %d\n", priv->icon_size);
-             width = height = 24;
-           }
-       }
 
+      ensure_icon_size (image, &flags, &width, &height);
       info = gtk_icon_theme_lookup_icon (icon_theme,
                                          priv->data.name.icon_name,
                                          MIN (width, height), flags);
-      if (info)
-        {
-          GtkStyleContext *context;
-          gboolean was_symbolic;
-
-          context = gtk_widget_get_style_context (GTK_WIDGET (image));
-          priv->data.name.pixbuf =
-            gtk_icon_info_load_symbolic_for_context (info,
-                                                     context,
-                                                     &was_symbolic,
-                                                     NULL);
-          priv->was_symbolic = was_symbolic;
-          gtk_icon_info_free (info);
-        }
 
-      if (priv->data.name.pixbuf == NULL)
-       {
-         priv->data.name.pixbuf =
-           gtk_widget_render_icon_pixbuf (GTK_WIDGET (image),
-                                           GTK_STOCK_MISSING_IMAGE,
-                                           priv->icon_size);
-         priv->was_symbolic = FALSE;
-       }
+      priv->data.name.pixbuf = ensure_stated_icon_from_info (image, info);
+
+      if (info)
+       gtk_icon_info_free (info);
     }
 }
 
 static void
-ensure_pixbuf_for_gicon (GtkImage      *image,
-                         GtkStateFlags  state)
+ensure_pixbuf_for_gicon (GtkImage        *image,
+                         GtkStateFlags    state)
 {
   GtkImagePrivate *priv = image->priv;
   GdkScreen *screen;
   GtkIconTheme *icon_theme;
-  GtkSettings *settings;
   gint width, height;
   GtkIconInfo *info;
   GtkIconLookupFlags flags;
@@ -1548,63 +1603,32 @@ ensure_pixbuf_for_gicon (GtkImage      *image,
 
   screen = gtk_widget_get_screen (GTK_WIDGET (image));
   icon_theme = gtk_icon_theme_get_for_screen (screen);
-  settings = gtk_settings_get_for_screen (screen);
+
   flags = GTK_ICON_LOOKUP_USE_BUILTIN;
+
   if (priv->use_fallback)
     flags |= GTK_ICON_LOOKUP_GENERIC_FALLBACK;
-  if (priv->data.gicon.pixbuf == NULL ||
-      (priv->was_symbolic && priv->last_rendered_state != state))
+
+  if ((priv->data.gicon.pixbuf == NULL) ||
+      (priv->last_rendered_state != state))
     {
       priv->last_rendered_state = state;
+
       if (priv->data.gicon.pixbuf)
         {
           g_object_unref (priv->data.gicon.pixbuf);
           priv->data.gicon.pixbuf = NULL;
        }
-      if (priv->pixel_size != -1)
-       {
-         width = height = priv->pixel_size;
-          flags |= GTK_ICON_LOOKUP_FORCE_SIZE;
-       }
-      else if (!gtk_icon_size_lookup_for_settings (settings,
-                                                  priv->icon_size,
-                                                  &width, &height))
-       {
-         if (priv->icon_size == -1)
-           width = height = 48;
-         else
-           {
-             g_warning ("Invalid icon size %d\n", priv->icon_size);
-             width = height = 24;
-           }
-       }
 
+      ensure_icon_size (image, &flags, &width, &height);
       info = gtk_icon_theme_lookup_by_gicon (icon_theme,
                                             priv->data.gicon.icon,
                                             MIN (width, height), flags);
-      if (info)
-        {
-          GtkStyleContext *context;
-          gboolean was_symbolic;
-
-          context = gtk_widget_get_style_context (GTK_WIDGET (image));
-          priv->data.gicon.pixbuf =
-            gtk_icon_info_load_symbolic_for_context (info,
-                                                     context,
-                                                     &was_symbolic,
-                                                     NULL);
-          priv->was_symbolic = was_symbolic;
-          gtk_icon_info_free (info);
-        }
 
-      if (priv->data.gicon.pixbuf == NULL)
-       {
-         priv->data.gicon.pixbuf =
-           gtk_widget_render_icon_pixbuf (GTK_WIDGET (image),
-                                           GTK_STOCK_MISSING_IMAGE,
-                                           priv->icon_size);
-         priv->was_symbolic = FALSE;
-       }
+      priv->data.gicon.pixbuf = ensure_stated_icon_from_info (image, info);
+
+      if (info)
+       gtk_icon_info_free (info);
     }
 }
 
@@ -1628,11 +1652,11 @@ gtk_image_draw (GtkWidget *widget,
       gfloat xalign, yalign;
       GdkPixbuf *pixbuf;
       GtkStateFlags state;
-      gboolean needs_state_transform;
       GtkStyleContext *context;
 
       misc = GTK_MISC (widget);
       context = gtk_widget_get_style_context (widget);
+
       state = gtk_widget_get_state_flags (widget);
 
       gtk_style_context_save (context);
@@ -1655,8 +1679,6 @@ gtk_image_draw (GtkWidget *widget,
       x = floor (xpad + ((gtk_widget_get_allocated_width (widget) - priv->required_width) * xalign));
       y = floor (ypad + ((gtk_widget_get_allocated_height (widget) - priv->required_height) * yalign));
 
-      needs_state_transform = state != 0;
-
       switch (priv->storage_type)
         {
 
@@ -1669,18 +1691,12 @@ gtk_image_draw (GtkWidget *widget,
           pixbuf = gtk_widget_render_icon_pixbuf (widget,
                                                   priv->data.stock.stock_id,
                                                   priv->icon_size);
-
-          /* already done */
-          needs_state_transform = FALSE;
           break;
 
         case GTK_IMAGE_ICON_SET:
           pixbuf =
             gtk_icon_set_render_icon_pixbuf (priv->data.icon_set.icon_set,
                                              context, priv->icon_size);
-
-          /* already done */
-          needs_state_transform = FALSE;
           break;
 
         case GTK_IMAGE_ANIMATION:
@@ -1706,17 +1722,7 @@ gtk_image_draw (GtkWidget *widget,
           break;
 
        case GTK_IMAGE_ICON_NAME:
-         if (state & GTK_STATE_FLAG_INSENSITIVE)
-           {
-             ensure_pixbuf_for_icon_name (image, 0);
-           }
-         else
-           {
-             ensure_pixbuf_for_icon_name (image, state);
-             /* Already done by the loading function? */
-             if (priv->was_symbolic)
-               needs_state_transform = FALSE;
-           }
+          ensure_pixbuf_for_icon_name (image, state);
          pixbuf = priv->data.name.pixbuf;
          if (pixbuf)
            {
@@ -1725,24 +1731,14 @@ gtk_image_draw (GtkWidget *widget,
          break;
 
        case GTK_IMAGE_GICON:
-         if (state & GTK_STATE_FLAG_INSENSITIVE)
-           {
-             ensure_pixbuf_for_gicon (image, 0);
-           }
-         else
-           {
-             ensure_pixbuf_for_gicon (image, state);
-             /* Already done by the loading function? */
-             if (priv->was_symbolic)
-               needs_state_transform = FALSE;
-           }
+          ensure_pixbuf_for_gicon (image, state);
          pixbuf = priv->data.gicon.pixbuf;
          if (pixbuf)
            {
              g_object_ref (pixbuf);
            }
          break;
-         
+
         case GTK_IMAGE_EMPTY:
         default:
           g_assert_not_reached ();
@@ -1752,30 +1748,9 @@ gtk_image_draw (GtkWidget *widget,
 
       if (pixbuf)
         {
-          if (needs_state_transform)
-            {
-              GtkIconSource *source;
-              GdkPixbuf *rendered;
-
-              source = gtk_icon_source_new ();
-              gtk_icon_source_set_pixbuf (source, pixbuf);
-              /* The size here is arbitrary; since size isn't
-               * wildcarded in the souce, it isn't supposed to be
-               * scaled by the engine function
-               */
-              gtk_icon_source_set_size (source,
-                                        GTK_ICON_SIZE_SMALL_TOOLBAR);
-              gtk_icon_source_set_size_wildcarded (source, FALSE);
-
-              rendered = gtk_render_icon_pixbuf (context, source, (GtkIconSize) -1);
-              gtk_icon_source_free (source);
-
-              g_object_unref (pixbuf);
-              pixbuf = rendered;
-            }
-
-          gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y);
-          cairo_paint (cr);
+          gtk_render_icon (context, cr,
+                           pixbuf,
+                           x, y);
 
           g_object_unref (pixbuf);
         }
@@ -1915,8 +1890,8 @@ gtk_image_calc_size (GtkImage *image)
 
   priv->need_calc_size = 0;
   context = gtk_widget_get_style_context (widget);
-  state = gtk_widget_get_state_flags (widget);
 
+  state = gtk_widget_get_state_flags (widget);
   gtk_style_context_save (context);
   gtk_style_context_set_state (context, state);
 
@@ -1938,12 +1913,12 @@ gtk_image_calc_size (GtkImage *image)
                                                 context, priv->icon_size);
       break;
     case GTK_IMAGE_ICON_NAME:
-      ensure_pixbuf_for_icon_name (image, 0);
+      ensure_pixbuf_for_icon_name (image, state);
       pixbuf = priv->data.name.pixbuf;
       if (pixbuf) g_object_ref (pixbuf);
       break;
     case GTK_IMAGE_GICON:
-      ensure_pixbuf_for_gicon (image, 0);
+      ensure_pixbuf_for_gicon (image, state);
       pixbuf = priv->data.gicon.pixbuf;
       if (pixbuf)
        g_object_ref (pixbuf);